class Carousel {

    constructor(obj) {

        if(obj.el){
            if(typeof obj.el ==="object"){
                this.carousel = obj.el;
            }else{
                throw  new TypeError("el 属性类型错误")
            }
        }else{
            throw  new Error("没找到 el 属性");
        }


        this.isStart = false;
        this.isAutoPlay = false;
        this.isJump = false;
        this.carouselInner = this.carousel.getElementsByClassName("carousel-inner")[0];
        this.carouselItem = this.carouselInner.children;
        const activeObj = this.carouselInner.getElementsByClassName("active")[0];
        this.activeNum = 1;
        let imgArr = this.carouselInner.getElementsByTagName("img");

        if(this.carouselItem.length===0){
            throw  new Error("没有找到轮播图");
        }


        if(obj.duration){
            if(typeof obj.duration ==="number"){
                this.duration  = obj.duration
            }else{
                throw new TypeError("duration 属性类型错误")
            }

        }else{
            this.duration = 500;
        }


        if( typeof obj.autoPlayInterval === "number"){
            if(obj.autoPlayInterval <= this.duration){
                this.autoPlayInterval = this.duration;
            }else{
                this.autoPlayInterval = obj.autoPlayInterval;
            }
        }else{
            this.autoPlayInterval = 2500;
        }


        if(typeof obj.timingFunction ==="string"){

            switch (obj.timingFunction) {
                case "linear":
                    this.timingFunction = "linear";
                    break;
                case "ease":
                    this.timingFunction = "ease";
                    break;
                case "ease-in":
                    this.timingFunction = "ease-in";
                    break;
                case "ease-out":
                    this.timingFunction = "ease-out";
                    break;
                case "ease-in-out":
                    this.timingFunction = "ease-in-out";
                    break;
                default:
                    throw new TypeError("timingFunction 属性输入错误")
            }


        }else{
            this.timingFunction = "ease";
        }


        for (let i = 0, len = this.carouselItem.length; i < len; i++) {
            if (this.carouselItem[i] === activeObj) {
                this.activeNum = i + 1;
            }
        }



        let carouselInnerInnerStr = this.carouselItem[this.carouselItem.length-1].outerHTML;
        let carouselIndicatorHTML = "<ul class='carousel-indicators'>";


        for (let i = 0, len = imgArr.length; i < len; i++) {

            this.carouselItem[i].setAttribute("data-slide-index",i+1);
            carouselInnerInnerStr += this.carouselItem[i].outerHTML;

            if (i + 1 === this.activeNum) {
                carouselIndicatorHTML += "<li class='active' data-slide-to='" + (i + 1) + "'></li>";
            } else {
                carouselIndicatorHTML += "<li data-slide-to='" + (i + 1) + "'></li>";
            }

        }


        carouselInnerInnerStr += this.carouselItem[0].outerHTML;
        carouselIndicatorHTML += "<ul/>";

        this.carouselInner.innerHTML = carouselInnerInnerStr;

        this.carouselItem[0].classList.remove("active");
        this.carouselItem[this.carouselItem.length-1].classList.remove("active");

        this.carouselItem[0].setAttribute("data-slide-index",0);
        this.carouselItem[this.carouselItem.length-1].setAttribute("data-slide-index",this.carouselItem.length-1);

        this.carousel.insertAdjacentHTML("beforeend", carouselIndicatorHTML);
        this.carouselIndicators = this.carousel.getElementsByClassName("carousel-indicators")[0];
        this.carouselIndicatorsItem = this.carouselIndicators.children;

        if(obj.autoSize === true){
            const height = this.getHeight(this.carousel.parentNode);
            const width = this.getWidth(this.carousel.parentNode);
            this.carousel.style.width = width+"px";
            this.carousel.style.height = height+"px";
            for(let i=0,len=imgArr.length;i<len;i++){
                imgArr[i].style.height = height+"px";
                imgArr[i].style.width = width+"px";
            }
        }else{
            this.carousel.style.width = this.getWidth(this.carouselItem[0])+"px";
            this.carousel.style.height =  this.getHeight(this.carouselItem[0])+"px";
        }


        this.offset = this.getWidth(this.carousel);
        this.translate =  -this.offset * (this.activeNum);
        this.carouselInner.style.transform = "translate("+this.translate+"px)";
        const that = this;

        for(let i=0,len = this.carouselIndicatorsItem.length;i<len;i++){
            this.carouselIndicatorsItem[i].addEventListener("click",function (e) {
                that.jump(e);
            });
        }


        this.carousel.getElementsByClassName("carousel-control-prev")[0].addEventListener("click",function () {
            that.prev();
        });

        this.carousel.getElementsByClassName("carousel-control-next")[0].addEventListener("click",function () {
            that.next();
        });


        if( obj.autoPlay === true){
            this.autoPlay();
        }


    }

    next() {

        if(arguments[0] === true){

            if (this.isStart === true  || this.isJump === true) {
                return false;
            }

        }else{

            if (this.isStart === true  || this.isAutoPlay === true || this.isJump === true) {
                return false;
            }
        }


        this.isStart = true;
        const that = this;
        this.activeNum++;

        if(this.carouselInner.style.transition === "" || this.carouselInner.style.transition === "none"){
            this.carouselInner.style.transition  = "transform "+this.duration+"ms "+this.timingFunction;
        }


        if (this.activeNum === this.carouselItem.length - 1) {


            this.carouselIndicatorsItem[this.activeNum - 2].classList.remove("active");
            this.carouselIndicatorsItem[0].classList.add("active");
            this.translate -= that.offset;
            this.carouselInner.style.transform = "translate3d("+this.translate+"px,0px,0px)";

            setTimeout(function () {
                that.carouselInner.style.transition = "none";
                that.activeNum = 1;
                that.translate = -that.offset;
                that.carouselInner.style.transform = "translate3d("+that.translate+"px,0px,0px)";
                that.carouselItem[that.carouselItem.length-2].classList.remove("active");
                that.carouselItem[1].classList.add("active");
                that.isStart = false;
            },this.duration);


        } else {

            this.carouselIndicatorsItem[this.activeNum - 2].classList.remove("active");
            this.carouselIndicatorsItem[this.activeNum - 1].classList.add("active");
            this.translate -= that.offset;
            this.carouselInner.style.transform = "translate3d("+this.translate+"px,0px,0px)";

            setTimeout(function () {
                that.carouselItem[that.activeNum - 1].classList.remove("active");
                that.carouselItem[that.activeNum].classList.add("active");
                that.isStart = false;
            },this.duration);

        }
    }

    prev(){

        if (this.isStart === true || this.isAutoPlay === true || this.isJump === true) {
            return false;
        }

        this.isStart = true;
        const that = this;
        this.activeNum--;

        if(this.carouselInner.style.transition === "" || this.carouselInner.style.transition === "none"){
            this.carouselInner.style.transition  = "transform "+this.duration+"ms "+this.timingFunction;
        }


        if (this.activeNum === 0) {

            this.carouselIndicatorsItem[this.activeNum].classList.remove("active");
            this.carouselIndicatorsItem[this.carouselItem.length - 3].classList.add("active");
            this.translate += this.offset;
            this.carouselInner.style.transform = "translate3d("+this.translate+"px,0px,0px)";

            setTimeout(function () {
                that.carouselInner.style.transition = "none";
                that.activeNum = that.carouselItem.length - 2;
                that.translate = -that.offset * that.activeNum;
                that.carouselInner.style.transform = "translate3d("+that.translate+"px,0px,0px)";
                that.carouselItem[1].classList.remove("active");
                that.carouselItem[that.carouselItem.length -2].classList.add("active");
                that.isStart = false;
            },this.duration);


        } else {

            this.carouselIndicatorsItem[this.activeNum].classList.remove("active");
            this.carouselIndicatorsItem[this.activeNum -1].classList.add("active");
            this.translate += this.offset;
            this.carouselInner.style.transform = "translate3d("+this.translate+"px,0px,0px)";

            setTimeout(function () {
                that.carouselItem[that.activeNum + 1].classList.remove("active");
                that.carouselItem[that.activeNum].classList.add("active");
                that.isStart = false;
            },this.duration)


        }
    }


    autoPlay() {

        if(this.isAutoPlay === true){
            return false;
        }

        this.isAutoPlay = true;
        const that = this;
        // this.autoPlayId = setInterval(function () {
        //     that.next(true);
        // }, this.autoPlayInterval);

        this.autoPlayAnimation();

        this.carousel.addEventListener("mouseenter",function(){
            clearTimeout(that.autoPlayId);
            that.isAutoPlay = false;
        });

        this.carousel.addEventListener("mouseleave",function () {
            that.autoPlay();
        });
    }

    autoPlayAnimation(){
        let that = this;
        this.autoPlayId = setTimeout(function () {
            that.next(true);
            that.autoPlayAnimation();
        },this.autoPlayInterval);

    }


    autoPlayClear(){

        if(this.isAutoPlay === false){
            return false;
        }

        this.isAutoPlay = false;
        const that = this;
        clearTimeout(this.autoPlayId);
        this.carousel.removeEventListener("mouseenter",function(){
            clearTimeout(that.autoPlayId);
            that.isAutoPlay = false;
        });
        this.carousel.removeEventListener("mouseleave",function () {
            that.autoPlay();
        });
    }


    jump(e){

        let target = parseInt(e.target.getAttribute("data-slide-to"));

        if (this.isStart === true || this.isAutoPlay === true || this.isJump === true) {
            return false;
        }

        if (target > this.activeNum) {

            this.isJump = true;

            for (let i = 0, len = this.carouselItem.length; i < len; i++) {

                if (i !== target && i !== this.activeNum) {
                    this.carouselItem[i].style.display = "none";
                }

            }

            this.carouselInner.style.left = -this.translate+"px";

            if(this.carouselInner.style.transition === "" || this.carouselInner.style.transition === "none"){
                this.carouselInner.style.transition  = "transform "+this.duration+"ms "+this.timingFunction;
            }

            const that = this;
            this.carouselIndicatorsItem[this.activeNum - 1].classList.remove("active");
            this.carouselIndicatorsItem[target -1].classList.add("active");
            this.translate -= this.offset;
            this.carouselInner.style.transform = "translate3d("+this.translate+"px,0px,0px)";

            setTimeout(function () {
                that.carouselInner.style.transition = "none";
                for (let i = 0, len = that.carouselItem.length; i < len; i++) {
                    that.carouselItem[i].style.display = "block";
                }
                that.translate = target* - that.offset;
                that.carouselInner.style.transform = "translate3d("+that.translate+"px,0px,0px)";
                that.carouselInner.style.left = "0px";
                that.carouselItem[that.activeNum].classList.remove("active");
                that.activeNum = target;
                that.carouselItem[target].classList.add("active");
                that.isJump = false
            },this.duration)

        }

        if (target < this.activeNum) {

            this.isJump = true;

            if(this.carouselInner.style.transition === "" || this.carouselInner.style.transition === "none"){
                this.carouselInner.style.transition  = "transform "+this.duration+"ms "+this.timingFunction;
            }


            for (let i = 0, len = this.carouselItem.length; i < len; i++) {

                if (i !== target && i !== this.activeNum) {
                    this.carouselItem[i].style.display = "none";
                }

            }


            this.carouselInner.style.left = (-this.translate)-this.offset+"px";

            if(this.carouselInner.style.transition === "" || this.carouselInner.style.transition === "none"){
                this.carouselInner.style.transition  = "transform "+this.duration+"ms "+this.timingFunction;
            }


            const that = this;
            this.carouselIndicatorsItem[this.activeNum - 1].classList.remove("active");
            this.carouselIndicatorsItem[target -1].classList.add("active");
            this.translate += this.offset;
            this.carouselInner.style.transform = "translate3d("+this.translate+"px,0px,0px)";

            setTimeout(function () {
                that.carouselInner.style.transition = "none";
                for (let i = 0, len = that.carouselItem.length; i < len; i++) {
                    that.carouselItem[i].style.display = "block";
                }
                that.translate = target* -that.offset;
                that.carouselInner.style.transform = "translate3d("+that.translate+"px,0px,0px)";
                that.carouselInner.style.left = "0px";
                that.carouselItem[that.activeNum].classList.remove("active");
                that.activeNum = target;
                that.carouselItem[target].classList.add("active");
                that.isJump = false
            },this.duration)
        }
    }


    getWidth(el) {
        const style = window.getComputedStyle ? window.getComputedStyle(el, null) : el.currentStyle;
        let val = parseFloat(style.width);
        let which = ["Left", "Right"];

        if (val === 0) {
            return 0;
        }

        if (style.boxSizing === "content-box") {

            return val;

        }

        if (style.boxSizing === "border-box") {

            for (let i = 0, len = which.length; i < len; i++) {
                val -= parseFloat(style["border" + which[i] + "Width"]) || 0;
                val -= parseFloat(style["padding" + which[i]]) || 0;
            }

            return val;
        }

        return false;
    }

    getHeight(el) {
        const style = window.getComputedStyle ? window.getComputedStyle(el, null) : el.currentStyle;
        let val = parseFloat(style.height);
        let which = ["Top", "Bottom"];

        if (val === 0) {
            return 0;
        }

        if (style.boxSizing === "content-box") {

            return val;

        }

        if (style.boxSizing === "border-box") {

            for (let i = 0, len = which.length; i < len; i++) {
                val -= parseFloat(style["border" + which[i] + "Width"]) || 0;
                val -= parseFloat(style["padding" + which[i]]) || 0;
            }

            return val;
        }

        return false;
    }

}